package com.example.scrambledpuzzle;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.MediaStore.Images.ImageColumns;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;

import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import android.util.Log;

import android.view.DragEvent;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.DragShadowBuilder;
import android.view.View.OnTouchListener;
import android.widget.AdapterView;
import android.widget.BaseAdapter;

import android.widget.GridView;
import android.widget.ImageView;

import android.widget.TextView;

public class Puzzle extends Activity {
	Integer[] resourcePics={
			R.drawable.cow,
			R.drawable.dog ,
			R.drawable.elephant,
			R.drawable.fish,
			R.drawable.fox,
			R.drawable.peacock,
			//R.drawable.beavers,
			//R.drawable.bike,
			//R.drawable.car

	};
	
	boolean fromGallery=false;
	ContentResolver cr;
	private MediaPlayer mp = null;
	TextView  txtNoOfMoves;
	GridView gdView;
	int resId,rnd;
	int ctr=0;
	int match=0;
	Bitmap scratch;
	int ctrNoOfMoves=0;
	String key;
	/// Tag for logging
	private static final String TAG = "PuzzleActivity";

	// number of pieces to split
	private static final int NUM_OF_PIECES = 9;

	// list to keep track of image pieces in the gallery
	List<Integer> mGalleryList=new ArrayList<Integer>();
	//List<Integer> mResourcePicsList=new ArrayList<Integer>();
	List<Integer> mResourcePicsList= Arrays.asList(resourcePics);

	// bitmap array pieces

	Bitmap[] mBmpPieces=new Bitmap[NUM_OF_PIECES];

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_puzzle);
		cr =getContentResolver();
		ImageView rightArrow=(ImageView) findViewById(R.id.right);
		txtNoOfMoves=(TextView) findViewById(R.id.displayNoOfMoves);
		
		ImageView homeButton = (ImageView) findViewById(R.id.home);


		resId=getIntent().getIntExtra("BitmapImage", 0);
		String path=getIntent().getExtras().getString("CameraPath");
		final Uri uriPath=getIntent().getExtras().getParcelable("GalleryPath");
		
		if (path != null){
			scratch=BitmapFactory.decodeFile(path);
			//scratch= decodeSampledBitmapFromResource(path,3264, 2448);
			fromGallery=true;

		}else if(uriPath !=null){

			// Do this in a background thread, since we are fetching a large image from the web
			//Thread thread=new Thread() {
			//public void run() {
			//scratch = getBitmap("image_file_name.jpg", uriPath);
			scratch = getBitmap(uriPath);
			fromGallery=true;

			//}
			//};
			//thread.start();
		}
		else if(resId != 0){
			//scratch=decodeSampledBitmapFromResource(getResou`1rces(), resId,620,440);
			scratch=BitmapFactory.decodeResource(getResources(),resId);
			fromGallery=false;
		}
		//Bitmap resizedScratch=Bitmap.createScaledBitmap(scratch, 3264, 2448, true);


		// create pieces
		if (scratch !=null){

			resizeBitmap();

			createBitmapPieces(scratch);

			//Create GridView
			gdView=(GridView) findViewById(R.id.gridviewToAssemble);
			//Display display = getWindowManager().getDefaultDisplay();
			//gdView.setColumnWidth(display.getWidth()/3);

			//Create the adapter of GridView
			gdView.setAdapter(new GridAdapter(this));

			gdView.setOnTouchListener(new OnTouchListener(){

				@Override
				public boolean onTouch(View arg1, MotionEvent event) {
					if(event.getAction()==MotionEvent.ACTION_DOWN){


						GridView parent=(GridView)arg1;
						int x = (int) event.getX();
						int y = (int) event.getY();


						int position = parent.pointToPosition(x, y);
						ImageView viewToBeDragged=(ImageView) parent.getChildAt(position);

						if (viewToBeDragged.getTag() != null){

							ClipData.Item item=new ClipData.Item((CharSequence)viewToBeDragged.getTag().toString());
							ClipDescription NOTE_STREAM_TYPES= new ClipDescription ((CharSequence)viewToBeDragged.getTag().toString(),new String[ ] {ClipDescription.MIMETYPE_TEXT_PLAIN});
							ClipData clipData=new ClipData(NOTE_STREAM_TYPES,item);
							clipData.addItem(item);
							DragShadowBuilder shadowBuilder=new  View.DragShadowBuilder(viewToBeDragged);
							viewToBeDragged.startDrag(clipData, shadowBuilder, viewToBeDragged, 0);


							return true;
						}else{

							return false;
						}
					}
					return true;
				}

			});

			gdView.setOnDragListener(new View.OnDragListener() {

				@Override
				public boolean onDrag(View v, DragEvent event) {

					int action=event.getAction();
					switch(event.getAction()) {
					case DragEvent.ACTION_DRAG_STARTED:
						break;
					case DragEvent.ACTION_DRAG_ENTERED:
						break;
					case DragEvent.ACTION_DRAG_EXITED:

						break;
					case DragEvent.ACTION_DROP:
						//int i;

						GridView parent=(GridView) v;
						GridAdapter adapter=(GridAdapter) parent.getAdapter();
						int x=(int)event.getX();
						int y=(int) event.getY();
						int position=parent.pointToPosition(x, y);
						int relativePosition=position-parent.getFirstVisiblePosition();

						ImageView dragged=(ImageView) event.getLocalState();

						ImageView dropped=(ImageView)parent.getChildAt(relativePosition);


						if (position>AdapterView.INVALID_POSITION){
							int dropLocationIndex=(Integer) dropped.getTag();
							int imageindex=(Integer)dragged.getTag();

							int draggedCellPosition=mGalleryList.indexOf(imageindex);
							ImageView draggedCell=(ImageView) parent.getChildAt(draggedCellPosition);


							if ((imageindex >= 0) && (imageindex < NUM_OF_PIECES)){
								int droppedGalleryIndex=mGalleryList.indexOf(dropLocationIndex);
								int draggedGalleryIndex=mGalleryList.indexOf(imageindex);

								dropped.setImageBitmap(mBmpPieces[imageindex]);


								mGalleryList.remove(droppedGalleryIndex);
								mGalleryList.add(droppedGalleryIndex, imageindex);
								dropped.setTag(imageindex);
								draggedCell.setImageBitmap(mBmpPieces[dropLocationIndex]);
								mGalleryList.remove(draggedGalleryIndex);
								mGalleryList.add(draggedGalleryIndex,dropLocationIndex);
								draggedCell.setTag(dropLocationIndex);
								if(dropLocationIndex != imageindex){
									ctrNoOfMoves++;
									txtNoOfMoves.setText( Integer.toString( ctrNoOfMoves ));
								}



							}


							adapter.notifyDataSetChanged();
							/*for(int k=0;k< mGalleryList.size();k++){
						Log.v(TAG,"GalleryIndex = " + mGalleryList.get(k));
						}*/

							///Logic to add completion sounnd for the puzzle.
							for(int j=0;j<mGalleryList.size(); j++){

								if (mGalleryList.get(j) == j){
									match++;

									if (match == mGalleryList.size()){
										match=0;
										playSound(R.raw.tada);
									}
								} else {
									match=0;
									break;
								}
							}
							//Log.v(TAG,"match = " + match);



						}


						break;
					case DragEvent.ACTION_DRAG_ENDED:
						playSound(R.raw.cluck);

						break;
					}
					return true;


				}

			});
		}

		homeButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent homeScreen=new Intent(Puzzle.this,PhoneGalllery.class);

				startActivity(homeScreen);

			}
		});

		rightArrow.setOnClickListener(new View.OnClickListener(){

			@Override
			public void onClick(View v) {
				int resourceId;
				//scratch=null;
				if(fromGallery){
					scratch=generateImage();
					resizeBitmap();
				}
				else{
					ctrNoOfMoves=0;
					txtNoOfMoves.setText("");

					// Generate random number
					/*  int imageCount = mResourcePicsList.size() - 1;

			    Random random = new Random();
			    int resourceId = random.nextInt(imageCount);*/
					if(ctr >= mResourcePicsList.size()) {
						//resourceId=mResourcePicsList.get(0);
						ctr=0;
					}
					resourceId=mResourcePicsList.get(ctr);
					ctr++;
					scratch=BitmapFactory.decodeResource(getResources(),resourceId);
					resizeBitmap();
				}
				mGalleryList.clear();

				createBitmapPieces(scratch);
				gdView.setAdapter(new GridAdapter(getApplicationContext()));
				//GridAdapter gridAdapter=(GridAdapter)grid.getAdapter();
				//grid.setAdapter(new GridAdapter(this));
				//gridAdapter.notifyDataSetChanged();
				//grid.invalidate();


			}

		});

	}

	public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
			int reqWidth, int reqHeight) {

		// First decode with inJustDecodeBounds=true to check dimensions
		final BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeResource(res, resId, options);

		// Calculate inSampleSize
		options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

		// Decode bitmap with inSampleSize set
		options.inJustDecodeBounds = false;
		return BitmapFactory.decodeResource(res, resId, options);
	}
	public static int calculateInSampleSize(
			BitmapFactory.Options options, int reqWidth, int reqHeight) {
		// Raw height and width of image
		final int height = options.outHeight;
		final int width = options.outWidth;
		int inSampleSize = 1;

		if (height > reqHeight || width > reqWidth) {

			// Calculate ratios of height and width to requested height and width
			final int heightRatio = Math.round((float) height / (float) reqHeight);
			final int widthRatio = Math.round((float) width / (float) reqWidth);

			// Choose the smallest ratio as inSampleSize value, this will guarantee
			// a final image with both dimensions larger than or equal to the
			// requested height and width.
			inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
		}

		return inSampleSize;
	}

	private void resizeBitmap() {



		//scratch.recycle();
		int width = scratch.getWidth();
		int height = scratch.getWidth();
		float aspectRatio = (float) width / (float) height;
		int newWidth = 800;
		int newHeight = (int) (800 / aspectRatio);   
		Bitmap.createScaledBitmap(scratch, newWidth, newHeight, true);
		//return Bitmap.createScaledBitmap(bmap, newWidth, newHeight, true);

	}

	//plays a sound file
	private void playSound(int sFile)
	{
		//set up MediaPlayer   
		final int medFile = sFile;

		Thread thread = new Thread(new Runnable()       {

			public void run() {
				mp = MediaPlayer.create(getApplicationContext(), medFile);
				mp.start();
			}
		});
		thread.start();

	}

	private Bitmap getBitmap(Uri url)
	{

		File cacheDir;
		// if the device has an SD card
		if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
			cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),".OCFL311");
		} else {
			// it does not have an SD card
			//	cacheDir=ActivityPicture.this.getCacheDir();
			cacheDir=this.getCacheDir();
		}
		if(!cacheDir.exists())
			cacheDir.mkdirs();

		//File f=new File(cacheDir, tag);

		try {

			BitmapFactory.Options options = new BitmapFactory.Options();
			android.content.res.AssetFileDescriptor fd = getContentResolver().openAssetFileDescriptor(url,"r");

			Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, options);
			fd.close();
			return bitmap;
		} catch (Exception ex) {

			ex.printStackTrace();
			return null;
		}
	}
	Bitmap generateImage() {
		// Get list of images accessible by cursor

		String[] columns = new String[] {
				ImageColumns._ID,
				ImageColumns.TITLE,
				ImageColumns.DATA,
				ImageColumns.MIME_TYPE,
				ImageColumns.SIZE };
		Cursor cursor = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
				columns, null, null, null);

		// Collect Picture IDs
		cursor.moveToFirst();
		ArrayList<Integer> picList = new ArrayList<Integer>();
		while (!cursor.isAfterLast()) {
			picList.add(cursor.getInt(0));
			cursor.moveToNext();
		}// end for

		// Generate random number
		int imageCount = picList.size() - 1;

		Random random = new Random();
		int randomInt = random.nextInt(imageCount);


		// Extract the image
		//int picID = picList.get(randomInt);
		int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
		cursor.moveToPosition(randomInt);
		String filePath = cursor.getString(columnIndex);
		return BitmapFactory.decodeFile(filePath);
		//return decodeSampledBitmapFromResource(filePath,3264,2448);


	}// end Generate Image


	/// function to create pieces
	void createBitmapPieces(Bitmap source){
		scratch=null;
		int k=0;
		int width=source.getWidth();
		int height=source.getHeight();
		for(int i=0;i<3;i++){
			for(int j=0;j<3;j++){
				mBmpPieces[k]=Bitmap.createBitmap(source,(width*j)/3,(i*height)/3,width/3,height/3);
				//mBmpInGallery[k] = true;
				mGalleryList.add(k);
				k++;
			}
		}
		// shuffle pieces
		Collections.shuffle(mGalleryList);

	} 

	public class GridAdapter extends BaseAdapter{
		private Context mContext;
		int mGalleryItemBackground;

		public GridAdapter(Context con) {
			mContext=con;
			//TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
			// mGalleryItemBackground = a.getResourceId(
			// R.styleable.Gallery1_android_galleryItemBackground,0);
			//a.recycle();

		}

		@Override
		public int getCount() {
			return mBmpPieces.length;
		}

		@Override
		public Object getItem(int arg0) {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public long getItemId(int arg0) {
			// TODO Auto-generated method stub
			return 0;
		}

		@Override
		public View getView(int arg0, View arg1, ViewGroup arg2) {
			ImageView iView;
			if (arg1 == null) {  // if it's not recycled, initialize some attributes

				iView = new ImageView(mContext);


				iView.setAdjustViewBounds(true);

				int index= mGalleryList.get(arg0);

				iView.setImageBitmap(mBmpPieces[index]);
				iView.setTag(index);


			} else {
				iView = (ImageView) arg1;

			}
			return iView;

		}

	}


	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.puzzle, menu);
		return true;
	}

}
